package com.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Title: DateUtil.java
 * @Description: 日期辅助类
 * @author Yanjh 2011-8-16 上午11:34:04
 * @version V1.0
 */
public  class DateUtil {
	

    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);

    private static String yearMonthDay = "yyyy-MM-dd";
    
    private static String yearMonthDayNoBar = "yyyyMMdd";
    
    private static final  int number24 = 24;
    private static final int number1000 = 1000;
    private static final int number1 = 1;
    private static final  int number2 = 2;
    private static final int number3 = 3;
    private static final int number4 = 4;
    private static final int number5 = 5;
    private static final int number6 = 6;
    private static final int number7 = 7;
    private static final int number8 = 8;
    private static final int number9 = 9;
    private static final int number10 = 10;
    private static final int number11 = 11;
    private static final int number12 = 12;
    private static final int number20 = 20;
    private static final int number28 = 28;
    private static final int number29 = 29;
    private static final int number30 = 30;
    private static final int number31 = 31;
    private static final int number3600 = 3600;
    private static final int number400 = 400;
    private static final int number100 = 100;
    
    /**
     * @Title: getDateString
     * @Description: 使用"yyyy-MM-dd HH:mm:ss"格式化日期
     * @author Yanjh
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString(Date date) {
        return getDateString(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * @Title: getDateString
     * @Description: 格式化日期
     * @author Yanjh
     * @param date 日期.
     * @param format 模式
     * @return String 返回类型
     */
    public static String getDateString(Date date, String format) {
        if (date != null) {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.format(date);
        }
        return null;
    }

    /**
     * @Title: getDateString
     * @Description: 使用"yyyyMMddHHmmss"格式化日期
     * @author Wujl
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString14(Date date) {
        return getDateString(date, "yyyyMMddHHmmss");
    }

    /**
     * @Title: getDateString
     * @Description: 使用"yyyy-MM-dd HH:mm:ss"格式化日期
     * @author Wujl
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString19(Date date) {
        return getDateString(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * @Title: getDateString
     * @Description: 使用"yyyyMMdd"格式化日期
     * @author Wujl
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString8(Date date) {
        return getDateString(date, yearMonthDayNoBar);
    }

    /**
     * @Title: getDateString
     * @Description: 使用"yyyy-MM-dd"格式化日期
     * @author HouJunChang
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString10(Date date) {
        return getDateString(date, yearMonthDay);
    }

    /**
     * @Title: getDateString
     * @Description: 使用"yyyy-MM"格式化日期
     * @author Wujl
     * @param date 日期.
     * @return String 返回类型
     */
    public static String getDateString7(Date date) {
        return getDateString(date, "yyyy-MM");
    }

    /**
     * 返回年份("获取年").
     * 
     * @param date 日期
     * @return int 返回年份
     */
    public static int getYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    /**
     * 返回月份("获取月").
     * 
     * @param date 日期
     * @return int 返回月份
     */
    public static int getMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MONTH) + 1;
    }

    /**
     * 返回日份("获取日").
     * 
     * @param date 日期
     * @return int 返回日份
     */
    public static int getDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 返回小时("获取时").
     * 
     * @param date 日期
     * @return int 返回小时
     */
    public static int getHour(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 返回分钟("获取分").
     * 
     * @param date 日期
     * @return int 返回分钟
     */
    public static int getMinute(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MINUTE);
    }

    /**
     * 返回秒钟("获取秒").
     * 
     * @param date 日期
     * @return int 返回秒钟
     */
    public static int getSecond(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.SECOND);
    }

    /**
     * 返回毫秒("获取毫秒").
     * 
     * @param date 日期
     * @return int 返回毫秒
     */
    public static long getMillis(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getTimeInMillis();
    }

    /**
     * 日期相加("日期增加月数").
     * 
     * @param date 日期
     * @param month 月数
     * @return 返回相加后的日期
     */
    public static Date addMonth(Date date, int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, month);
        // 增加一天

        return c.getTime();
    }

    /**
     * 日期相加.
     * 
     * @param date 日期
     * @param day 天数
     * @return 返回相加后的日期
     */
    public static Date addDate(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(getMillis(date) + ((long) day) * number24 * number3600 * number1000);
        return c.getTime();
    }

    /**
     * 日期相减.
     * 
     * @param date 日期
     * @param day 天数
     * @return 返回相减后的日期
     */
    public static Date diffDate1(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(getMillis(date) - ((long) day) * number24 * number3600 * number1000);
        return c.getTime();
    }

    /**
     * O 日期相减.
     * 
     * @param date 日期
     * @param date1 日期
     * @return 返回相减后的日期
     */
    public static int diffDate(Date date, Date date1) {
        return (int) ((getMillis(date) - getMillis(date1)) / (number24 * number3600 * number1000));
    }

    /**
     * O 时间相减.
     * 
     * @param date 日期
     * @param date1 日期
     * @return 返回相减后的时间单位秒
     */
    public static int diffTime(Date date, Date date1) {
        return (int) ((getMillis(date) - getMillis(date1)) / number1000);
    }

    /**
     * 日期相减.
     * 
     * @param date1 日期字符串
     * @param date2 日期字符串
     * @param format 日期字符串的格式 如：yyyyMMdd ; yyyy-MM-dd
     * @return 返回相减后的天数
     * @throws ParseException 期望
     */
    public static int diffDate(String date1, String date2, String format) throws ParseException {
        if (!StringUtil.isStrNotNullAndNotEmpty(format)) {
            format = yearMonthDay;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();

        c1.setTime(sdf.parse(date1));
        c2.setTime(sdf.parse(date2));
        return (int) ((getMillis(c1.getTime()) - getMillis(c2.getTime())) / (number24 * number3600 * number1000));
    }
    
    /**
     * 日期相减.
     * @param date1 日期字符串
     * @param date2 日期字符串
     * @param format 日期字符串的格式 如：yyyyMMdd ; yyyy-MM-dd
     * @return 返回相减后的天数
     * @throws ParseException 期望
     */
    public static int diffDate(Date date1, Date date2, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String dateString1 = sdf.format(date1);
        String dateString2 = sdf.format(date2);
        return diffDate(dateString1, dateString2, format);
    }

    /**
     * 日期相减("日期加减年").
     * 
     * @param date 日期
     * @param years 年份
     * @return 返回相减后的日期
     * @throws ParseException 期望
     */
    public static Date addYear(Date date, int years) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);
        Calendar c = Calendar.getInstance();
        c.setTime(sdf.parse(sdf.format(date)));
        c.add(Calendar.YEAR, years);
        // 增加年份

        return c.getTime();
    }

    //
    /**
     * 根据两个日期，得到两个日期之间的年月 日期字符串数组.
     * 
     * @param d1 日期
     * @param d2 日期
     * @return 返回字符型日期时间数组
     * @throws ParseException 期望
     */
    public static String[] getDates(Date d1, Date d2) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);

        Calendar cd = Calendar.getInstance();

        ArrayList<String> stringList = new ArrayList<String>();
        while (d1.compareTo(d2) <= 0) {
            cd.setTime(sdf.parse(sdf.format(d1)));
            String dString = sdf.format(d1);
            stringList.add(dString);
            cd.add(Calendar.MONTH, 1);
            // 增加一天
            d1 = cd.getTime();
        }
        String[] arr = new String[stringList.size()];
        return stringList.toArray(arr);
    }

    /**
     * 返回日期("js的毫秒转换为日期").
     * 
     * @param millis 毫秒
     * 
     * @return 返回日期
     */
    public static Date jsmillis2Date(long millis) {
        return new Date(millis * number1000);
    }

    /**
     * 根据年月得到该月的开始和结束日期.
     * 
     * @param ym 年月字符串，格式 yyyy-MM
     * @return Object[] 首末两个时间
     * @throws ParseException 期望
     */
    public static Object[] getDateYMMinAndMax(String ym) throws ParseException {
        Object[] objs = new Object[2];
        SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);
        Calendar c = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c.setTime(sdf.parse(ym + "-01"));
        int end = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c2.setTime(sdf.parse(ym + "-" + end));

        objs[0] = c.getTime();
        objs[1] = c2.getTime();

        return objs;
    }

    /**
     * 根据年得到该年的开始和结束日期.
     * 
     * @param yy 年字符串，格式 yyyy
     * @return Object[] 首末两个时间
     * @throws ParseException 期望
     */
    public static Object[] getDateYYMinAndMax(String yy) throws ParseException {
        Object[] objs = new Object[2];
        SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);
        Calendar c = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c.setTime(sdf.parse(yy + "-01-01"));
        c2.setTime(sdf.parse(yy + "-12-31"));

        objs[0] = c.getTime();
        objs[1] = c2.getTime();

        return objs;
    }

    /**
     * 根据季度得到该季度的开始和结束日期.
     * 
     * @param yy 年份
     * @param quarter 季度 1-4
     * @return get 得到
     * @throws ParseException 期望
     */
    public static Object[] getDateQuarterMinAndMax(String yy, int quarter) throws ParseException {
        Object[] objs = new Object[2];
        int[][] array = { { number1, number2, number3 }, { number4, number5, number6 }, { number7, number8, number9 }, { number10, number11, number12 } };

        int startmonth = array[quarter - 1][0];
        int endmonth = array[quarter - 1][2];

        Object[] dtstarts = getDateYMMinAndMax(yy + "-" + startmonth);
        Object[] dtends = getDateYMMinAndMax(yy + "-" + endmonth);
        objs[0] = dtstarts[0];
        objs[1] = dtends[1];
        return objs;
    }

    /**
     * 
     * @param y 年.
     * @return get 得到
     * @throws ParseException 期望
     */
    public static Object[] getPentecostMinAndMax(Date y) throws ParseException {
        Object[] objs = new Object[2];
        int day = getDay(y);
        String dateStart = "";
        String dateEnd = "";
        String dateStr = getDateString(y, "yyyyMM");
        Object[] monObj = getDateYMMinAndMax(getDateString(y, "yyyy-MM"));
        String monEnd = getDateString((Date) monObj[1], yearMonthDayNoBar);
        if (day >= 1 && day <= number10) {
            dateStart = dateStr + "01";
            dateEnd = dateStr + "10";
        } else if (day >= number11 && day <= number20) {
            dateStart = dateStr + "11";
            dateEnd = dateStr + "20";
        } else {
            dateStart = dateStr + "21";
            dateEnd = monEnd;
        }
        objs[0] = dateStart;
        objs[1] = dateEnd;
        return objs;
    }

    /**
     * 两个字符串的时间差.
     * 
     * @param begin 起始时间
     * @param end 结束时间
     * @return 天数
     * @throws ParseException 期望
     */
    public static int countDays(String begin, String end) throws ParseException {
        int days = 0;

        DateFormat df = new SimpleDateFormat(yearMonthDayNoBar);
        Calendar cb = Calendar.getInstance();
        Calendar ce = Calendar.getInstance();

        cb.setTime(df.parse(begin));
        ce.setTime(df.parse(end));
        while (cb.before(ce)) {
            days++;
            cb.add(Calendar.DAY_OF_YEAR, 1);
        }

        return days + 1;
    }

    /**
     * 字符串转换为Date型.
     * 
     * @param date 时间
     * @param format 
     * @return get 得到
     * @throws ParseException 期望
     */
    public static Date getData(String date, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.parse(date);
    }

    /** 
     * @Title: parseTimestamp 
     * @Description: 
     * @Auth wentaolu
     * @Date Jul 22, 2016 2:25:41 PM
     * @param str 线.
     * @param formate 组合
     * @return parse 解析
     * @throws ParseException 希望
     * @throws 
     */
    public static long parseTimestamp(String str, String formate) throws ParseException {
        Date date = getData(str, formate);
        return date.getTime();
    }

    /**
     * 字符串加天数，返回字符串.
     * 
     * @param time 当前时间
     * @param day 天数
     * @param str 日期格式
     * @return String 线
     * @throws ParseException 期望
     */
    public static String addDaysInString(String time, int day, String str) throws ParseException {
        Date d = getData(time, str);
        // 将字符串转换为date型
        d = addDate(d, day);
        // 加天数
        time = getDateString(d, str);
        // 将date型转换为字符串
        return time;
    }

    /**
     * 计算当月1日到当天的天数,当年1月1日到当天的天数.
     * 
     * @param now 当前时间
     * @return Object 物品
     * @throws ParseException 期望
     */
    public static Object[] countMonthDaysAndYearDays(String now) throws ParseException {
        // 计算当月1日到当天的天数
        int days = 0;
        Object[] objs = new Object[number10];
        String begin = now.substring(0, number6) + "01";

        DateFormat df = new SimpleDateFormat(yearMonthDayNoBar);
        Calendar cb = Calendar.getInstance();
        Calendar ce = Calendar.getInstance();

        cb.setTime(df.parse(begin));
        ce.setTime(df.parse(now));
        while (cb.before(ce)) {
            days++;
            cb.add(Calendar.DAY_OF_YEAR, 1);
        }

        objs[0] = begin;
        objs[1] = days + 1;

        // 当年1月1日到当天的天数
        days = 0;
        begin = now.substring(0, number4) + "0101";

        cb.setTime(df.parse(begin));
        ce.setTime(df.parse(now));
        while (cb.before(ce)) {
            days++;
            cb.add(Calendar.DAY_OF_YEAR, 1);
        }

        objs[number2] = begin;
        objs[number3] = days + 1;
        objs[number4] = now;

        return objs;
    }

    /**
     * 计算两个日期相差的月数.
     * 
     * @param date1 日期字符串
     * @param date2 日期字符串
     * @return get 得到
     */
    public static int getMonthSpace(String date1, String date2) {
        int result = 0;

        try {
            SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);

            Calendar c1 = Calendar.getInstance();
            Calendar c2 = Calendar.getInstance();

            c1.setTime(sdf.parse(date1));
            c2.setTime(sdf.parse(date2));
            result = c2.get(Calendar.MONDAY) - c1.get(Calendar.MONTH);
        } catch (Exception e) {
            LOGGER.error(StackTraceUtil.getStackTrace(e));
        }
        return result == 0 ? 1 : Math.abs(result);

    }

    /**
     * 根据当前日期，减去一周的日期.
     * 
     * @param date 日期字符串
     * @return convert 转化
     */
    public static String convertWeekByDate(Date date) {
        // 设置时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(yearMonthDay);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, -7);
        return sdf.format(cal.getTime());
    }

    /**
     * 根据当前日期，减去月数,计算过去的某一个月.
     * 
     * @param date 当前日期
     * @param subtractor 减去月数
     * @return convert 转化
     */
    public static String convertLastMonth(Date date, int subtractor) {
        // 设置时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, subtractor);
        return sdf.format(cal.getTime());
    }

    /**
     * @param startTime 开始时间(yyyy-MM-dd).
     * @param endTime 截止时间(yyyy-MM-dd)
     * @return get 得到
     * @throws Exception 期望
     */
    public static List<String> getStartAndEndTimeWeek(String startTime, String endTime) throws Exception {
        List<String> startAndEndTime = new ArrayList<String>();
        SimpleDateFormat sdFormat = new SimpleDateFormat(yearMonthDay);
        Date startDate = new Date();
        Date endDate = new Date();
        Calendar calendar = Calendar.getInstance();
        if (StringUtil.isStrNotNullAndNotEmpty(startTime) && startTime.length() == number10
                && StringUtil.isStrNotNullAndNotEmpty(endTime) && endTime.length() == number10) {
            /*
             * 第一步：找到起始日期
             */
            startDate = sdFormat.parse(startTime);
            calendar.setTime(startDate);
            int startWeekDay = calendar.get(Calendar.DAY_OF_WEEK);
            /*
             * 如果不是星期一，将日期向后移，直到找到第一个星期一为止，并将日期设置为起始日期
             */
            while (Calendar.MONDAY != startWeekDay) {
                calendar.add(Calendar.DAY_OF_YEAR, 1);
                startWeekDay = calendar.get(Calendar.DAY_OF_WEEK);
            }
            startDate = calendar.getTime();
            /*
             * 第二步：找到截止日期
             */
            endDate = sdFormat.parse(endTime);
            calendar.setTime(endDate);
            int endWeekDay = calendar.get(Calendar.DAY_OF_WEEK);
            /*
             * 如果截止日期不是星期天，那么将日期向前移，直到找到第一个星期天为止，并将日期设置 为截止日期
             */
            while (Calendar.SUNDAY != endWeekDay) {
                calendar.add(Calendar.DAY_OF_YEAR, -1);
                endWeekDay = calendar.get(Calendar.DAY_OF_WEEK);
            }
            endDate = calendar.getTime();
        }
        if (endDate.before(startDate)) {
            String errorString = "false";
            startAndEndTime.add(errorString);
        } else {
            startAndEndTime.add(sdFormat.format(startDate));
            startAndEndTime.add(sdFormat.format(endDate));
        }
        return startAndEndTime;
    }
    
    /**
     * isLeapYear:判断一年是否是闰年. <br/>
     *
     * @author shuxinwu
     * @param year 年
     * @return is 是
     */
    public static boolean isLeapYear(int year) {
        if ((year % number4 == 0 && year % number100 != 0) || year % number400 == 0) {
            return true;
        }
        return false;
    }
    
    /**
     * getMonthDay:获取每个月有多少天. <br/>
     *
     * @author shuxinwu
     * @param year 年
     * @param month 月
     * @return get 得到
     */
    public static int getMonthDay(int year, int month) {
        int[] allMonthDayLeapYear = new int[]{number31, number29, number31, number30, number31, number30, number31, number31, number30, number31, number30, number31};
        int[] allMonthDayAverYear = new int[]{number31, number28, number31, number30, number31, number30, number31, number31, number30, number31, number30, number31};
        if (isLeapYear(year)) {
            return allMonthDayLeapYear[month];
        }
        return allMonthDayAverYear[month];
    }
    
    /**
     * getWeekDay:当前时间是星期几. <br/>
     *  星期日：1；星期一：2；。。。。。。星期六：7
     * @author shuxinwu
     * @param date 日期字符串
     * @return get 得到
     */
    public static int getWeekDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK);
    }
    
    /** 
     * @Title: compareTimeByString 
     * @author: shuxinwu
     * @Description: 比较两个字符串时间，dateString1<=dateString2时，返回true
     * @time: Jan 12, 2016 3:03:45 PM
     * @param dateString1 小
     * @param dateString2 大
     * @return compare 比较
     * @throws ParseException 期望
     * @return: boolean 体系
     * @throws
     */
    public static boolean compareTimeByString(String dateString1, String dateString2) throws ParseException {
        Date date1 = getData(dateString1, "yyyy-MM-dd");
        Date date2 = getData(dateString2, "yyyy-MM-dd");
        if (date1.before(date2) || dateString1.equals(dateString2)) {
            return true;
        }
        return false;
    }
    
    /** 
     * @Title: getNextDate 
     * @Description:得到向后的日期.
     * @Auth shuxinwu
     * @Date 2016年7月4日 上午11:24:01
     * @param date 日期
     * @param format 日期格式
     * @param days 向后几天
     * @return
     * @throws 
     */
    public static String getNextDate(Date date,String format,int days){
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	cal.add(Calendar.DAY_OF_YEAR, days);
    	date = cal.getTime();
    	return getDateString(date,format);
    }
    
    /** 
     * @Title: getPrevious 
     * @Description: 得到向前的日期.
     * @Auth shuxinwu
     * @Date 2016年7月4日 下午4:49:13
     * @param date 日期
     * @param format 日期格式
     * @param days 向前几天
     * @return
     * @throws 
     */
    public static String getPrevious(Date date,String format,int days){
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	cal.add(Calendar.DAY_OF_YEAR, -(days));
    	date = cal.getTime();
    	return getDateString(date,format);
    }
    
    /** 
     * @Title: getNextDate 
     * @Description: 得到向后的日期.
     * @Auth shuxinwu
     * @Date 2016年7月27日 下午4:56:50
     * @param date 日期
     * @param days 向后几天
     * @return
     * @throws 
     * @version 2.1.1
     */
    public static Date getNextDate(Date date,int days){
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	cal.add(Calendar.DAY_OF_YEAR, days);
    	return cal.getTime();
    }
    
    /** 
     * @Title: getPrevious 
     * @Description: 得到向前的日期.
     * @Auth shuxinwu
     * @Date 2016年7月27日 下午4:56:59
     * @param date 日期
     * @param days 向前几天
     * @return
     * @throws 
     * @version 2.1.1
     */
    public static Date getPrevious(Date date,int days){
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	cal.add(Calendar.DAY_OF_YEAR, -(days));
    	return cal.getTime();
    }

	public static long getDateByMillis(long time) {
		SimpleDateFormat simpleTimeFormat = new SimpleDateFormat(
				"yyyy-MM-dd", Locale.getDefault());
		Date date = new Date(time);
		String dateStr = simpleTimeFormat.format(date);
		try {
			date = simpleTimeFormat.parse(dateStr);
		} catch (ParseException e) {
			LOGGER.error(StackTraceUtil.getStackTrace(e));
		}
		return getMillis(date);
	}
}
